package org.jeecg.codegeneweb.util;

import lombok.Data;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FolderCompare {


    /**
     * 根据路径获取所有的文件夹和文件,及文件的md5值
     * @param path 路径
     */
    public static List<FileModel> getFiles(String path, String grade) throws IOException {

        List<FileModel> fileModels=new ArrayList<>();
        File folder = new File(path);
        List<File> files=getFileList(folder);
        /*Object[] files = getFileList(folder).toArray();

        Arrays.sort(files);*/
        for (File file : files) {

            // 去掉根目录,正则的\\\\,转义为java的\\,再转义为\

            String fullfilepath=file.getAbsolutePath().replaceAll("\\\\", "/");
            String pathtr=path.replaceAll("\\\\", "/");
            String relativename=fullfilepath.substring(pathtr.length(),fullfilepath.length());
            //System.out.println(relativename);
            //key = key.replaceAll(path, "");
            String md5 = "";// 文件夹不比较md5值
            FileModel fileModel = new FileModel();
            if (file.isDirectory()) {
                fileModel.setDir(true);
                fileModel.setMd5("");
            }else {
                fileModel.setDir(false);
                fileModel.setFile(file);
                fileModel.setMd5(DigestUtils.md5Hex(new FileInputStream(file)));
            }
            fileModel.setFullfilename(fullfilepath);
            fileModel.setRelativename(relativename);
            if(grade.equalsIgnoreCase("new"))
                fileModel.setOrgOrDest("新生成的文件夹");
            else
                fileModel.setOrgOrDest("原有的文件夹");
            fileModels.add(fileModel);
        }
        return fileModels;
    }
    /**
     * 递归获取路径下所有文件夹和文件
     * @param folder 文件路径
     */
    private static List<File> getFileList(File folder) {
        List<File> list = new ArrayList<File>();
        File[] files = folder.listFiles();
        for (File file : files) {
            list.add(file);
            if (file.isDirectory()) {
                List<File> fileList = getFileList(file);
                list.addAll(fileList);
            }
        }
        return list;
    }



    /**
     * Steven,原来的有问题，现在fix
     * 比较两个文件集合的不同
     * @param fileOldList 文件集合
     * @param fileMap2 文件集合
     */
    public static List<FileModel> compareFileEhWithCollectionCal(List<FileModel> fileOldList, List<FileModel> fileNewList) {
        List<FileModel> resultList = new ArrayList<FileModel>();
        List<FileModel> backupFileOld=new ArrayList<>();
        //Collections.copy(fileOldList,backupFileOld);
        backupFileOld.addAll(fileOldList);
        List<FileModel> backupFileNew=new ArrayList<>();
        backupFileNew.addAll(fileNewList);
        //Collections.copy(fileNewList,backupFileNew);

        fileOldList.removeAll(fileNewList); //从 fileOldList 减去fileNewList 。结果在fileOldList，所以 fileOldList 值变化了
        resultList.addAll(fileOldList);
        backupFileNew.removeAll(backupFileOld);
        resultList.addAll(backupFileNew);

        return resultList;
    }
    public static void main(String[] args) throws IOException {
        String pathold = "D:\\workspace\\jeecg-boot\\src\\main\\java\\org\\jeecg\\modules\\demo";
        String pathnew = "D:\\jeecg4\\src\\main\\java\\org\\jeecg\\modules\\demo";
        // 获取路径下所有文件夹和文件,及文件的md5值
        List<FileModel> fileModelo=getFiles(pathold,"old");
        List<FileModel> fileModeld=getFiles(pathnew,"new");

        List<FileModel> resultList = new ArrayList<FileModel>();
        /*// 得到fileMap2中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap1, fileMap2));
        // 得到fileMap1中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap2, fileMap1));*/
        resultList.addAll(compareFileEhWithCollectionCal(fileModelo,fileModeld));
        // 输出最终结果
        for (FileModel fileModel : resultList) {
            System.out.println(fileModel.toString());
        }
    }
    public static int fileFoldCompare(String pathold,String pathnew) throws IOException {

        // 获取路径下所有文件夹和文件,及文件的md5值
        List<FileModel> fileModelo=getFiles(pathold,"old");
        List<FileModel> fileModeld=getFiles(pathnew,"new");

        List<FileModel> resultList = new ArrayList<FileModel>();
        /*// 得到fileMap2中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap1, fileMap2));
        // 得到fileMap1中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap2, fileMap1));*/
        resultList.addAll(compareFileEhWithCollectionCal(fileModelo,fileModeld));
        // 输出最终结果
        for (FileModel fileModel : resultList) {
            System.out.println(fileModel.toString());
        }
        return resultList.size();
    }
    public static List<FileModel> fileFoldComparebacklist(String pathold,String pathnew) throws IOException {

        // 获取路径下所有文件夹和文件,及文件的md5值
        List<FileModel> fileModelo=getFiles(pathold,"old");
        List<FileModel> fileModeld=getFiles(pathnew,"new");

        List<FileModel> resultList = new ArrayList<FileModel>();
        /*// 得到fileMap2中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap1, fileMap2));
        // 得到fileMap1中没有的文件夹和文件,及md5值不同的文件
        resultList.addAll(compareFile(fileMap2, fileMap1));*/
        resultList.addAll(compareFileEhWithCollectionCal(fileModelo,fileModeld));
        // 输出最终结果
        for (FileModel fileModel : resultList) {
            System.out.println(fileModel.toString());
        }
        return resultList;
    }
    @Data
    public static class FileModel {
        public File file;
        public String md5;
        public String fullfilename;
        public String relativename;
        public boolean isDir;//给一个默认值
        public String orgOrDest="源目录";//给一个默认值

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            FileModel fileModel = (FileModel) o;

            if(getFullfilename() != null && getRelativename().equals(fileModel.getRelativename())) {
                if (isDir())
                    return true;
                if(!isDir()){
                    if(getMd5()!=null&& getMd5().equalsIgnoreCase(fileModel.getMd5()))
                        return true;
                    else
                        return false;
                }
            }
            return false;
        }

        @Override
        public int hashCode() {
            int result = getFile() != null ? getFile().hashCode() : 0;
            result = 31 * result + (getMd5() != null ? getMd5().hashCode() : 0);
            result = 31 * result + (getFullfilename() != null ? getFullfilename().hashCode() : 0);
            result = 31 * result + (getRelativename() != null ? getRelativename().hashCode() : 0);
            result = 31 * result + (isDir() ? 1 : 0);
            result = 31 * result + (getOrgOrDest() != null ? getOrgOrDest().hashCode() : 0);
            return result;
        }

        @Override
        public String toString() {
            return "FileModel{" +

                    "orgOrDest=" + orgOrDest +
                    ", md5='" + md5 + '\'' +
                    ", fullfilename='" + fullfilename + '\'' +
                    ", relativename='" + relativename + '\'' +
                    ", isDir=" + isDir +
                    ", file='" + file + '\'' +
                    '}';
        }
    }
}